{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### The For Loop"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In Python, an **iterable** is an **object** capable of returning values one at a time.\n",
    "\n",
    "Many objects in Python are iterable: lists, strings, file objects and many more."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note: Our definition of an iterable did not state it was a collection of values - we only said it is an object that can return values one at a time - that's a subtle difference that we'll examine when we look into iterators and generators."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The **for** keyword can be used to iterate an iterable."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you come with a background in another programming language, you have probably seen **for** loops defined this way:\n",
    "\n",
    "``for (int i=0; i < 5; i++) {\n",
    "    //code block\n",
    "}``"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This form of the **for** loop is simply a _repetition_, very similar to a **while** loop - in fact it is equivalent to what we could write in Python as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "i = 0\n",
    "while i < 5:\n",
    "    #code block\n",
    "    print(i)\n",
    "    i += 1\n",
    "i = None"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But that's **NOT** what the **for** statement does in Python - the **for** statement is a way to **iterate** over iterables, and has nothing to do with the **for** loop we just saw. The closest equivalent we have in Python is the **while** loop written as above."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To use the **for** loop in Python, we **require** an iterable object to work with."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A simple iterable object is generated via the ``range()`` function"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "3\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "for i in range(5):\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Many objects are iterable in Python:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "for x in [1, 2, 3]:\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "h\n",
      "e\n",
      "l\n",
      "l\n",
      "o\n"
     ]
    }
   ],
   "source": [
    "for x in 'hello':\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a\n",
      "b\n",
      "c\n"
     ]
    }
   ],
   "source": [
    "for x in ('a', 'b', 'c'):\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "When we iterate over an iterable, each iteration returns the \"next\" value (or object) in the iterable:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(1, 2)\n",
      "(3, 4)\n",
      "(5, 6)\n"
     ]
    }
   ],
   "source": [
    "for x in [(1, 2), (3, 4), (5, 6)]:\n",
    "    print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can even assign the individual tuple values to specific named variables:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1 2\n",
      "3 4\n",
      "5 6\n"
     ]
    }
   ],
   "source": [
    "for i, j in [(1, 2), (3, 4), (5, 6)]:\n",
    "    print(i, j)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We will cover iterables in a lot more detail later in this course."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The **break** and **continue** statements work just as well in **for** loops as they do in **while** loops:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "for i in range(5):\n",
    "    if i == 3:\n",
    "        continue\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "2\n"
     ]
    }
   ],
   "source": [
    "for i in range(5):\n",
    "    if i == 3:\n",
    "        break\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The **for** loop, like the **while** loop, also supports an **else** clause which is executed if and only if the loop terminates normally (i.e. did not exit because of a **break** statement)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "No multiples of 7 encountered\n"
     ]
    }
   ],
   "source": [
    "for i in range(1, 5):\n",
    "    print(i)\n",
    "    if i % 7 == 0:\n",
    "        print('multiple of 7 found')\n",
    "        break\n",
    "else:\n",
    "    print('No multiples of 7 encountered')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "7\n",
      "multiple of 7 found\n"
     ]
    }
   ],
   "source": [
    "for i in range(1, 8):\n",
    "    print(i)\n",
    "    if i % 7 == 0:\n",
    "        print('multiple of 7 found')\n",
    "        break\n",
    "else:\n",
    "    print('No multiples of 7 encountered')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Similarly to the **while** loop, **break** and **continue** work just the same in the context of a **try** statement's **finally** clause."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------------------\n",
      "always runs\n",
      "0\n",
      "--------------------\n",
      "always runs\n",
      "1\n",
      "--------------------\n",
      "always runs\n",
      "2\n",
      "--------------------\n",
      "divided by 0\n",
      "always runs\n",
      "--------------------\n",
      "always runs\n",
      "4\n"
     ]
    }
   ],
   "source": [
    "for i in range(5):\n",
    "    print('--------------------')\n",
    "    try:\n",
    "        10 / (i - 3)\n",
    "    except ZeroDivisionError:\n",
    "        print('divided by 0')\n",
    "        continue\n",
    "    finally:\n",
    "        print('always runs')\n",
    "    print(i)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "There are a number of standard techniques to iterate over iterables:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "h\n",
      "e\n",
      "l\n",
      "l\n",
      "o\n"
     ]
    }
   ],
   "source": [
    "s = 'hello'\n",
    "for c in s:\n",
    "    print(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But sometimes, for indexable iterable types (e.g. sequences), we want to also know the index of the item in the loop:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 h\n",
      "1 e\n",
      "2 l\n",
      "3 l\n",
      "4 o\n"
     ]
    }
   ],
   "source": [
    "s = 'hello'\n",
    "i = 0\n",
    "for c in s:\n",
    "    print(i, c)\n",
    "    i += 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Slightly better approach might be:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 h\n",
      "1 e\n",
      "2 l\n",
      "3 l\n",
      "4 o\n"
     ]
    }
   ],
   "source": [
    "s = 'hello'\n",
    "\n",
    "for i in range(len(s)):\n",
    "    print(i, s[i])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "or even better:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 h\n",
      "1 e\n",
      "2 l\n",
      "3 l\n",
      "4 o\n"
     ]
    }
   ],
   "source": [
    "s = 'hello'\n",
    "\n",
    "for i, c in enumerate(s):\n",
    "    print(i, c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll come back to all these iteration techniques in a lot more detail throughout this course."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
